package spring.bean_post_processor;

import org.springframework.beans.BeansException;
import org.springframework.beans.factory.config.BeanPostProcessor;
import org.springframework.cglib.proxy.Enhancer;
import org.springframework.cglib.proxy.MethodInterceptor;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.stereotype.Component;

import java.lang.reflect.Proxy;

public class LearnPostProcessor {
    public static void main(String[] args) {
        ApplicationContext context = new AnnotationConfigApplicationContext(LearnPostProcessorConfig.class);
        TestProxyBean bean2 = context.getBean(TestProxyBean.class);
        bean2.printVal(1);
    }
}

@Configuration
@ComponentScan("spring.bean_post_processor")
class LearnPostProcessorConfig {

}

// 测试Log的bean
@Component
class TestLogBean {

}

// 测试代理的bean
@Component
class TestProxyBean {

    public TestProxyBean() {
    }

    public void printVal(int val) {
        System.out.println(val);
    }
}

// 日志增强：实现BeanPostProcessor接口的bean
@Component
class LogPostProcessor implements BeanPostProcessor {
    @Override
    public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
        if (bean instanceof TestLogBean)
            System.out.println("在 " + beanName + " 的初始化之前记录日志...");
        return bean;
    }

    @Override
    public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
        if (bean instanceof TestLogBean)
            System.out.println("在 " + beanName + " 的初始化之后记录日志...");
        return bean;
    }
}

// 代理增强：实现BeanPostProcessor接口的bean
@Component
class ProxyPostProcessor implements BeanPostProcessor {
    @Override
    public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
        if (!(bean instanceof TestProxyBean))
            return bean;
        // 使用cglib动态代理（由于原类没有接口，所以使用cglib动态代理）
        Enhancer enhancer = new Enhancer();
        enhancer.setSuperclass(bean.getClass());
        enhancer.setCallback((MethodInterceptor) (obj, method, args, proxy) -> {
            System.out.println("CGLIB代理，用原有参数执行一次");
            Object result = proxy.invoke(bean, args);
            System.out.println("CGLIB代理，改变逻辑使参数+1，再执行一次");
            Integer newArg = (Integer) args[0];
            result = proxy.invoke(bean, new Object[]{newArg + 1});
            System.out.println("CGLIB代理执行方法结束");
            return result;
        });
        return enhancer.create();
    }
}
